/*
 * @Descripttion: 字符串插值语法解析器,对${var}的表达式进行解析
 * @version: 1.0.0
 * @Author: lfzxs@qq.com
 * @Date: 2023-06-15 15:28:01
 * @LastEditors: lfzxs@qq.com
 * @LastEditTime: 2023-06-21 11:35:16
 */
package resolver

import (
	"os"
	"strings"

	"gitee.com/g_boot/configkit/loader"
)

type StringInterpolation struct {
}

func (sf *StringInterpolation) Resolution(cfgs loader.CfgSlice,env ...map[string]any) (result map[string]any,err error) {
	result = sf.ReplaceExp(nil,cfgs)
	return result,nil 
}


func (sf *StringInterpolation) ReplaceExp(env map[string]any, content loader.CfgSlice) map[string]any {
	result := make(map[string]interface{})

	for _, item := range content {
		key := item.Key.(string)
		switch value := item.Value.(type) { // value 表示 item.Value 转换成对应 type 的值
		case string: // item.Value 是字符串类型
			result[key] = sf.ExpandValueAnalysis(result, value)
		case loader.CfgSlice: // item.Value 是yaml.MapSlice类型
			result[key] = sf.ReplaceExp(result, value)
		case []interface{}: // []interface{} 类型
			var vals []interface{}
			for _, subint := range value {
				vs, ok := subint.(string)
				if ok {
					vals = append(vals, sf.ExpandValueAnalysis(result, vs))
					result[key] = vals
				}

				vMapSlice, ok := subint.(loader.CfgSlice)
				if ok {
					result[key] = sf.ReplaceExp(result, vMapSlice)
				}
			}

		default: // 未知类型
			result[key] = value
		}
	}
	return result
}


func (sf *StringInterpolation) ExpandValueAnalysis(env map[string]interface{}, value string) (realValue string) {
	realValue = value

	vLen := len(value)
	// 3 = ${}
	if vLen < 3 {
		return
	}

	temp := value
	result := ""
	exp := ""

	exp_start := strings.Index(temp, "${")
	exp_end := strings.Index(temp, "}")
	// vlen := len(temp)

	for exp_start >= 0 && exp_end > exp_start {
		result = result + temp[0:exp_start]

		exp = temp[exp_start : exp_end+1]

		vlen := len(temp)
		temp = temp[exp_end+1 : vlen]
		result = result + sf.ExpandExpEnv(env, exp)

		exp_start = strings.Index(temp, "${")
		exp_end = strings.Index(temp, "}")
	}
	result = result + temp

	return result
}

func  (sf *StringInterpolation) ExpandExpEnv(env map[string]interface{}, exp string) (realValue string) {
	vLen := len(exp)
	key := ""
	defaultV := ""
	// value start with "${"
	for i := 2; i < vLen; i++ {
		if exp[i] == ':' {
			key = exp[2:i]
			defaultV = exp[i+1 : vLen-1] // other string is default value.
			break
		} else if exp[i] == '}' {
			key = exp[2:i]
			break
		}
	}

	realValue, ok := env[key].(string)

	if !ok {
		realValue = os.Getenv(key)
		if realValue == "" {
			realValue = defaultV
		}
	}
	return

}
